前文提到頁是Innodb的基本存取單位,一般為16kb,Innodb為了實現功能其實設計了許多不同類型的頁,但我們不管那麼多,今天就只探討我們最關心的儲存記錄的頁(資料頁),官方又叫作索引(index)頁。
資列頁(16kb大小)的結構有7個部分
在資料頁內儲存一筆紀錄的流程為先向free space申請空間(一開始生成頁的時候並沒有user records區塊),
再將空間劃分到user records去,當所有的free space都被劃分到user records後,如果還有新紀錄要儲存就要另外生成新的資料頁。
前文提到資料內的標頭資訊很重要,今天要再詳細說明。
設計Innodb的工程師把新增的每一筆資料緊密無間的擺放在一起,稱其為堆疊(heap)。
每筆紀錄在堆疊中的相對位置稱為heap_no(是一個數字 ex:2),在頁面前面的heap_no值相對較小,在頁面後面的heap_no值相對較大,每新申請一筆紀錄的儲存空間時,該筆紀錄比物理位置在它前面的那筆紀錄heap_no值大1。
還有一個地方要注意,增加一筆紀錄到新生成的頁面時,頁面會自動再增加兩筆虛擬紀錄(infimum+supermum頁面中最小與最大的紀錄,不論插入多少紀錄也不管其主鍵值大小,infimum就是頁面中最小的紀錄,supermum就是頁面中最大的紀錄,這是規定!記住就對了!)
所以當我們插入兩筆資料時
mysql> insert into ryan_demo_table(c1,c2,c3,c4) values ('aaaa','bbb','cc','d'),('eeee','fff',NULL,NULL);
Query OK, 2 rows affected (0.02 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> select * from ryan_demo_table;
+------+-----+------+------+
| c1 | c2 | c3 | c4 |
+------+-----+------+------+
| aaaa | bbb | cc | d |
| eeee | fff | NULL | NULL |
+------+-----+------+------+
2 rows in set (0.00 sec)
這兩筆紀錄heap_no值分別會是2跟3(頁面自動再增加2筆虛擬紀錄infimum[heap_no:0]+supermum[heap_no:1]),而不是0跟1。
這屬性顧名思義就是用來找到下筆紀錄的,存放的是與下筆紀錄的真實距離(ex:3 從該筆紀錄往後找3個位元組會找到下筆紀錄),對於資料結構有點概念就會知道它是鏈結串列(透過一筆紀錄找到下一筆紀錄)。這邊要注意的是下筆紀錄並不是插入順序的下筆紀錄,而是資料照著主鍵值大小排序後,排在其後的下筆紀錄。
而infimum的下筆紀錄就是user records中主鍵最小的那筆,user records中主鍵最大那筆的下筆紀錄就是supermum,supermum的下筆紀錄就是0。
先認知Innodb儲存紀錄的結構就是一個按照主鍵大小排序的單向鏈結串列。
當我們刪掉其中一筆資料A,資料改變的只有3個地方(不包含n_owned的部分,這之後會再說明)。
當資料頁出現多筆被刪除的紀錄,可以透過next_record屬性組成一個垃圾鏈結串列。
再來還有一個值得注意的是如果我們之後新增資料,則會重複利用deleted_flag變成1的刪除紀錄,並不會重新申請新的儲存空間唷。